package com.olive.sign1;

import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.TreeMap;

import org.apache.commons.lang3.StringUtils;
import org.apache.commons.lang3.reflect.FieldUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.core.annotation.AnnotatedElementUtils;
import org.springframework.core.annotation.AnnotationUtils;
import org.springframework.util.ClassUtils;

import lombok.extern.slf4j.Slf4j;

/**
 * https://www.cnblogs.com/shamo89/p/17497921.html
 * https://www.cnblogs.com/xfeiyun/p/15665159.html
 * 
 * @author TR
 *
 */
@Slf4j
public class SignatureUtils {

	private final static String DELIMETER = "&";

	private final static String NOT_FOUND = "";

	/**
	 * 生成所有注有 SignatureField属性 key=value的 拼接
	 */
	public static String toSplice(Object object) {
		if (Objects.isNull(object)) {
			return StringUtils.EMPTY;
		}
		if (AnnotatedElementUtils.isAnnotated(object.getClass(), Signature.class)) {
			Signature sg = AnnotationUtils.findAnnotation(object.getClass(), Signature.class);
			switch (sg.sort()) {
			case Signature.ALPHA_SORT:
				return alphaSignature(object);
//				TODO
//			case Signature.ORDER_SORT:
//				return orderSignature(object);
			default:
				return alphaSignature(object);
			}
		}
		return toParserString(object);
	}

	/**
	 * 
	 * @param object
	 * @return
	 */
	private static String alphaSignature(Object object) {
		StringBuilder result = new StringBuilder();
		Map<String, String> map = new TreeMap<>();
		for (Field field : FieldUtils.getAllFields(object.getClass())) {
			if (field.isAnnotationPresent(SignatureField.class)) {
				field.setAccessible(true);
				try {
					if (AnnotatedElementUtils.isAnnotated(field.getType(), Signature.class)) {
						//字段的类如果添加了Signature注解
						if (!Objects.isNull(field.get(object))) {
							map.put(field.getName(), toSplice(field.get(object)));
						}
					} else {
						SignatureField sgf = field.getAnnotation(SignatureField.class);
						if (StringUtils.isNotEmpty(sgf.customValue()) || Objects.nonNull(field.get(object))) {
							String key = StringUtils.isNotBlank(sgf.customName()) ? sgf.customName() : field.getName();
							String value = StringUtils.isNotEmpty(sgf.customValue()) ? sgf.customValue()
									: toParserString(field.get(object));
							map.put(key, value);
						}
					}
				} catch (Exception e) {
					log.error("签名拼接(alphaSignature)异常", e);
				}
			}
		}

		for (Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator(); iterator.hasNext();) {
			Map.Entry<String, String> entry = iterator.next();
			result.append(entry.getKey()).append("=").append(entry.getValue());
			if (iterator.hasNext()) {
				result.append(DELIMETER);
			}
		}
		return result.toString();
	}

	/**
	 * 针对array, collection, simple property, map做处理
	 * 
	 * @param object
	 * @return
	 */
	private static String toParserString(Object object) {
		Class<?> type = object.getClass();
		if (BeanUtils.isSimpleProperty(type)) {
			return object.toString();
		}
		if (type.isArray()) {
			StringBuilder sb = new StringBuilder();
			for (int i = 0; i < Array.getLength(object); ++i) {
				sb.append(toSplice(Array.get(object, i)));
			}
			return sb.toString();
		}
		if (ClassUtils.isAssignable(Collection.class, type)) {
			StringBuilder sb = new StringBuilder();
			for (Iterator<?> iterator = ((Collection<?>) object).iterator(); iterator.hasNext();) {
				sb.append(toSplice(iterator.next()));
				if (iterator.hasNext()) {
					sb.append(DELIMETER);
				}
			}
			return sb.toString();
		}
		if (ClassUtils.isAssignable(Map.class, type)) {
			StringBuilder sb = new StringBuilder();
			for (Iterator<? extends Map.Entry<String, ?>> iterator = ((Map<String, ?>) object).entrySet()
					.iterator(); iterator.hasNext();) {
				Map.Entry<String, ?> entry = iterator.next();
				if (Objects.isNull(entry.getValue())) {
					continue;
				}
				sb.append(entry.getKey()).append("=").append(toSplice(entry.getValue()));
				if (iterator.hasNext()) {
					sb.append(DELIMETER);
				}
			}
			return sb.toString();
		}
		return NOT_FOUND;
	}

	public static void main(String[] args) {
		ClassDTO classDto = new ClassDTO();
		classDto.setAge(10);
		classDto.setName("huangjinjin");
		List<UserDTO> users = new ArrayList<>();
		UserDTO user = new UserDTO();
		user.setLove(Arrays.asList("footboot"));
		user.setName("yulove");
		Map<String, String> map = new HashMap<>();
		map.put("key1", "val1");
		map.put("key2", "val2");
		user.setMap(map);
		users.add(user);
		classDto.setUsers(users);
		
		System.out.println(toSplice(classDto));
	}
}
